package com.guozcc.sentinel.applicationrunner;

import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterParamFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.server.ClusterTokenServer;
import com.alibaba.csp.sentinel.cluster.server.SentinelDefaultTokenServer;
import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
import com.alibaba.csp.sentinel.cluster.server.config.ServerTransportConfig;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.api.PropertyKeyConst;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Properties;


@Component
public class ApplicationRunnerImpl implements ApplicationRunner {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

//    sentinel.nacos.address=127.0.0.1:8848
//    sentinel.nacos.namespace=0306b160-abb1-4947-8353-87ae4ab018f5
//    sentinel.nacos.group=SENTINEL_GROUP
//    sentinel.nacos.flowpostfix=-flow-rules
//    sentinel.nacos.parampostfix=-param-rules
//    sentinel.appname=bootweb


    @Value("${sentinel.nacos.address}")
    private String nacosAddress;
    @Value("${sentinel.nacos.namespace}")
    private String nacosNamespaceId;
    @Value("${sentinel.nacos.group}")
    private String nacosGroupId;
    @Value("${sentinel.nacos.flowpostfix}")
    private String flowPostfix;
    @Value("${sentinel.nacos.parampostfix}")
    private String paramPostfix;
    @Value("${sentinel.appname}")
    private String appName;
    @Value("${sentinel.server.port}")
    private int serverPort;
    @Override
    public void run(ApplicationArguments args) throws Exception {


        /**
         * 加载nacos规则参数
         */
        //流控参数
        ClusterFlowRuleManager.setPropertySupplier(namespace -> {
            Properties properties = new Properties();// 指定Nacos中namespace
            properties.put(PropertyKeyConst.SERVER_ADDR, nacosAddress);
            properties.put(PropertyKeyConst.NAMESPACE, nacosNamespaceId);
            ReadableDataSource<String, List<FlowRule>> ds = new NacosDataSource<>(properties, nacosGroupId,
                    namespace + flowPostfix,
                    source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
            return ds.getProperty();
        });
        //热点参数
        ClusterParamFlowRuleManager.setPropertySupplier(namespace -> {
            Properties properties = new Properties();// 指定Nacos中namespace
            properties.put(PropertyKeyConst.SERVER_ADDR, nacosAddress);
            properties.put(PropertyKeyConst.NAMESPACE, nacosNamespaceId);
            ReadableDataSource<String, List<ParamFlowRule>> ds = new NacosDataSource<>(properties, nacosGroupId,
                    namespace + paramPostfix,
                    source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {}));
            return ds.getProperty();
        });

        // Not embedded mode by default (alone mode).
        ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();

        // A sample for manually load config for cluster server.
        // It's recommended to use dynamic data source to cluster manage config and rules.
        // See the sample in DemoClusterServerInitFunc for detail.
        ClusterServerConfigManager.loadGlobalTransportConfig(new ServerTransportConfig()
                .setIdleSeconds(600)
                .setPort(serverPort));
        ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton(appName));

        // Start the server.
        tokenServer.start();

        log.info("服务端已加载流控规则：" + ClusterFlowRuleManager.getAllFlowRules());
        log.info("服务端已加载热点规则：" + ClusterParamFlowRuleManager.getAllParamRules());


//        new Thread(() -> {       }).start();
    }
}
